package net.xdclass.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import net.xdclass.common.constant.Cons;
import net.xdclass.common.enums.BizCodeEnum;
import net.xdclass.common.enums.MailType;
import net.xdclass.common.exception.BizException;
import net.xdclass.local.ThreadLocal;
import net.xdclass.user.feign.CouponFeignClient;
import net.xdclass.user.mapper.UserMapper;
import net.xdclass.common.model.LoginUser;
import net.xdclass.user.model.UserDO;
import net.xdclass.user.model.vo.UserVO;
import net.xdclass.user.request.GrantCouponRequest;
import net.xdclass.user.request.UserLoginRequest;
import net.xdclass.user.request.UserRegisterRequest;
import net.xdclass.user.service.NotifyService;
import net.xdclass.user.service.UserService;
import net.xdclass.common.utils.CommonUtil;
import net.xdclass.common.JsonData;
import net.xdclass.common.utils.JwtUtil;
import org.apache.commons.codec.digest.Md5Crypt;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private NotifyService notifyService;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private CouponFeignClient couponFeignClient;

    /**
     * 用户注册
     ** 邮箱验证码验证
     ** 密码加密
     ** 账号唯一性检查
     ** 插入数据库
     ** 新注册用户福利发放(TODO)
     * @param request
     * @return
     */
    @Override
    public JsonData register(UserRegisterRequest request) {
        checkParam(request);
        if (!notifyService.verifyCode(request.getMail(), MailType.USER_REGISTERY, request.getCode())){
            return JsonData.buildResult(BizCodeEnum.CODE_ERROR);
        }
        UserDO userDO = new UserDO();
        BeanUtils.copyProperties(request, userDO);
        userDO.setCreateTime(new Date());
        userDO.setSlogan("人生需要动态规划，学习需要贪心算法");
        userDO.setSecret("$1$" + CommonUtil.getRandomStr(8));
        //  密码加盐
        String cryptPwd = Md5Crypt.md5Crypt(request.getPwd().getBytes(), userDO.getSecret());
        userDO.setPwd(cryptPwd);
        // 账号唯一性检测
        if (!userMailUnique(userDO.getMail())){
            return JsonData.buildResult(BizCodeEnum.ACCOUNT_REPEAT);
        }
        int line = userMapper.insert(userDO);
        if (line == 1){
            log.info("用户 {} 注册成功，时间 {}", request.getName(), System.currentTimeMillis());
        }
        // 发放新用户福利
        userRegisterInitTask(userDO);
        return JsonData.buildSuccess();
    }

    /**
     * 查询当前用户
     *
     * @return
     */
    @Override
    public UserVO selectCurrentUser() {
        LoginUser loginUser = ThreadLocal.getLoginUser();
        QueryWrapper<UserDO> wrapper = new QueryWrapper<>();
        wrapper.eq("id", loginUser.getId());
        UserDO user = userMapper.selectOne(wrapper);
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }

    @Override
    public JsonData login(HttpServletRequest request, UserLoginRequest user) {
        QueryWrapper<UserDO> wrapper = new QueryWrapper<>();
        wrapper.eq("mail", user.getMail());
        UserDO userDO = userMapper.selectOne(wrapper);
        if (userDO == null){
            return JsonData.buildResult(BizCodeEnum.ACCOUNT_PWD_ERROR);
        }
        String cryptPwd = Md5Crypt.md5Crypt(user.getPwd().getBytes(), userDO.getSecret());
        if (!cryptPwd.equals(userDO.getPwd())){
            return JsonData.buildResult(BizCodeEnum.ACCOUNT_PWD_ERROR);
        }
        // 生成token
        LoginUser loginUser = new LoginUser();
        BeanUtils.copyProperties(userDO, loginUser);
        loginUser.setIp(CommonUtil.getIpAddr(request));
        String token = JwtUtil.getJwt(loginUser);
        return JsonData.buildSuccess(token);
    }

    /**
     * 用户账号唯一性检测
     * @param mail
     * @return
     */
    private boolean userMailUnique(String mail) {
        List<UserDO> mails = userMapper.selectList(new QueryWrapper<UserDO>().eq("mail", mail));
        return CollectionUtils.isEmpty(mails);
    }

    /**
     * 用户注册发放福利
     * @param user
     */
    private void userRegisterInitTask(UserDO user){
        GrantCouponRequest request = new GrantCouponRequest();
        request.setName(user.getName());
        request.setUserId(user.getId());
        JsonData jsonData = couponFeignClient.grantCouponForNewUser(request);
        log.info("发放新用户注册优惠券。用户【{}】，响应【{}】", user.getName(), jsonData);
        if (jsonData != null && !Cons.SUCCESS.equals(jsonData.getCode())){
            log.warn("新用户【{}】：【{}】新人优惠券发放失败。", request.getUserId(), request.getName());
            // TODO 插入数据库，人工补发，或者定时任务
        }
    }


    private void checkParam(UserRegisterRequest request){
        Assert.notNull(request, "用户注册信息不能为空.");
        if (StringUtils.isEmpty(request.getCode())) throw new BizException(BizCodeEnum.CODE_ERROR);
        if (StringUtils.isEmpty(request.getMail())) throw new BizException(BizCodeEnum.ACCOUNT_MAIL_LOSE);
        if (StringUtils.isEmpty(request.getPwd())) throw new BizException(BizCodeEnum.ACCOUNT_PWD_LOSE);
    }
}
